#include <pthread.h>
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>

static pthread_mutex_t mtx = PTHREAD_MUTEX_INITIALIZER;
static pthread_cond_t cond = PTHREAD_COND_INITIALIZER;
static int avail = 0;
static int n;

static void* producer(void* arg)
{
  int s;
  s = pthread_mutex_lock(&mtx);
  if (s != 0)
    printf("Failed to lock mutex in %s\n",__func__);

  avail++;
  printf("produced\n");

  s = pthread_mutex_unlock(&mtx);
  if (s != 0)
    printf("Failed to unlock mutex in %s\n",__func__);

  s = pthread_cond_signal(&cond);
  if (s != 0)
    printf("Failed to signal condvar\n");
  return NULL;
}

static void* consumer(void* arg)
{
  int n = (int)arg;
  for(int i = 0; i < n; i++){
    int s = pthread_mutex_lock(&mtx);
    if (s != 0)
      printf("Failed to lock mutex in %s\n",__func__);
    while (avail == 0) {
      s = pthread_cond_wait(&cond,&mtx);
      if (s != 0)
	printf("Failed to wait condvar\n");
    }
    while (avail > 0) {
      --avail;
      printf("consumed\n");
    }
    s = pthread_mutex_unlock(&mtx);
    if (s != 0)
      printf("Failed to unlock mutex in %s\n",__func__);
  }
  return NULL;
}

int main(int argc,char *argv[])
{
  n = (argc >1)?atoi(argv[1]):10;
  pthread_t t;
  pthread_create(&t,NULL,consumer,(void*)n);
  for(int i = 0; i< n; i++){
    pthread_t t;
    pthread_create(&t,NULL,producer,NULL);
    pthread_detach(t);
    sleep(2);
  }
  pthread_join(t,NULL);
  return 0;
}
